<!-- 计划排程 -->
<template>
  <basic-container>
    <avue-crud
      :option="option"
      :table-loading="loading"
      :defaults.sync="defaults"
      :data="data"
      :page.sync="page"
      :search.sync="search"
      :permission="permissionList"
      v-model="form"
      ref="crud"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @row-click="rowClick"
      @on-load="onLoad"
      @select="handSelect"
      @select-all="selectionAll"
    >
      <template slot="menu" slot-scope="{ row }">
        <el-button type="text" size="small" icon="el-icon-view" @click.stop="handleView(row)">详情</el-button>
      </template>
      <template slot="menuRight">
        <user-table-config :option="option" @confirm="(val) => handleSetUserConfig(val, pageCode)"></user-table-config>
      </template>
      <template slot="menuLeft">
        <!-- 派工 -->
        <el-button
          :disabled="disabledDispatch"
          type="primary"
          size="small"
          icon="el-icon-s-promotion"
          v-if="permission.workorderPlan_dispatch"
          @click="handleMenu({ type: 'dispatch' })"
          >排程派工</el-button
        >
        <!-- 撤销排程 -->
        <el-button :disabled="disabledWithdraw" type="danger" size="small" icon="el-icon-back" v-if="permission.workorderPlan_withdraw" @click="handleMenu({ type: 'revoke' })"
          >撤销排程</el-button
        >
        <el-button type="success" size="small" icon="el-icon-upload2" @click="handleImport">计划导入</el-button>
        <el-button v-if="false" type="warning" size="small" icon="el-icon-download" @click="$refs.exportComp.visible = true">导出</el-button>
      </template>
    </avue-crud>

    <!-- 计划排程 -->
    <el-dialog
      title="计划排程"
      v-if="dialogVisible"
      custom-class="dispatchDialog"
      append-to-body
      :fullscreen="true"
      :close-on-click-modal="false"
      :visible.sync="dialogVisible"
      :before-close="handleCloseDispatchDialog"
    >
      <div class="dispatch-title">
        <div class="dispatch-title-dot"></div>
        <div class="dispatch-title-text">工单信息</div>
      </div>
      <avue-form class="workInfoForm" v-model="dispatchDialog.workOrderInfo.form" :option="dispatchDialog.workOrderInfo.options"></avue-form>
      <div class="dispatch-title">
        <div class="dispatch-title-dot"></div>
        <div class="dispatch-title-text">产线派工</div>
      </div>
      <div class="dispatch-menu">
        <div class="leftWorkSection">
          产品工段：
          <template v-for="item in dispatchedSectionList"> <span class="finished"></span>{{ item }} </template>
          <template v-for="item in dispatchIngSectionList"> <span class="finishing"></span>{{ item }} </template>
          <template v-for="item in notDispatchSectionList"> <span class="notFinish"></span>{{ item }} </template>
        </div>
        <div class="rightInfo">
          <div class="legendList">
            <div class="legendItem"><span class="finished"></span>已排完</div>
            <div class="legendItem"><span class="finishing"></span>排程中</div>
            <div class="legendItem"><span class="notFinish"></span>未排</div>
          </div>
          <div class="dateDisplay">
            日期展示：
            <el-select size="mini" style="width: 100px" :disabled="isReadOnlyDispatch" v-model="backDay" placeholder="请选择开始展示日期" @change="handleChangeBackDay">
              <el-option v-for="item in backDayList" :key="item.value" :label="item.label" :value="item.value"> </el-option>
            </el-select>
          </div>
        </div>
      </div>
      <avue-crud
        ref="dispatchCrud"
        :table-loading="dispatchDialog.plan.loading"
        :option="dispatchDialog.plan.option"
        :data="dispatchDialog.plan.data"
        @row-del="dispatchPlanDel"
      >
        <template slot="sectionAndLineHeader" slot-scope="{ column }"> {{ (column || {}).label }} <i class="el-icon-plus" @click="addRow"></i> </template>
        <!-- 级联工段产线 -->
        <template slot="sectionAndLine" slot-scope="scope">
          <el-cascader
            :disabled="isReadOnlyDispatch"
            v-model="scope.row.sectionAndLine"
            :options="productLineSection"
            filterable
            placeholder="请选择工段产线"
            popper-class="sectionAndLinePopper"
            @change="(value) => handleLineChange(value, scope.row, scope.index)"
          ></el-cascader>
        </template>
        <!-- 优先级 -->
        <template slot="priority" slot-scope="scope">
          <el-select size="mini" :disabled="isReadOnlyDispatch" v-model="scope.row.priority" placeholder="请选择优先级" popper-class="priorityPopper">
            <el-option v-for="item in dispatchDialog.plan.priorityList" :key="item.value" :label="item.label" :value="item.value"> </el-option>
          </el-select>
        </template>
        <template slot="sectionPlanQuantity" slot-scope="scope">
          <el-input-number
            class="sectionPlanQuantity"
            size="mini"
            v-model="scope.row.sectionPlanQuantity"
            controls-position="right"
            @change="handleCalculateType1(scope.row, scope.index)"
            :min="0"
            :max="Number(dispatchDialog.workOrderInfo.form.planQuantity)"
            :precision="0"
            :disabled="isReadOnlyDispatch"
          ></el-input-number>
        </template>
        <template slot="uph" slot-scope="scope">
          <el-input-number
            class="uphNumber"
            size="mini"
            v-model="scope.row.uph"
            controls-position="right"
            :disabled="isReadOnlyDispatch"
            @change="handleCalculateType2(scope.row, scope.index)"
            :min="0"
          ></el-input-number>
        </template>
        <!-- 所有日期列 -->
        <template v-for="item in dateColumns" :slot="item.date" slot-scope="{ row, index }">
          <el-input-number
            class="dayPlanQuantity"
            v-if="item.date.endsWith(':dayPlanQuantity')"
            size="mini"
            v-model="row[item.date]"
            controls-position="right"
            :precision="0"
            :min="0"
            :disabled="!row.sectionAndLine[0] || !row.sectionAndLine[1] || isWorkday(row.planDateInfoList, item.date) || isReadOnlyDispatch || !row.sectionPlanQuantity"
            @change="handleCalculateType3(row, index, item.date)"
          ></el-input-number>
          <div v-if="item.date.endsWith(':dayPlanWorkHour')">{{ row[item.date] }}</div>
          <div v-if="item.date.endsWith(':dayRemainingWorkHourOfLine')">{{ row[item.date] }}</div>
        </template>
      </avue-crud>
      <div class="dispatch-title">
        <div class="dispatch-title-dot"></div>
        <div class="dispatch-title-text">产线资源</div>
      </div>
      <div class="gannt-menu">
        <el-form :inline="true" :model="dispatchDialog.productLine.form" class="demo-form-inline lineResource">
          <el-form-item label="产线：">
            <el-cascader
              size="mini"
              style="width: 300px"
              class="line-cascader"
              clearable
              collapse-tags
              :show-all-levels="true"
              :props="{ multiple: false }"
              :options="productLineSection"
              :disabled="isReadOnlyDispatch"
              :filterable="true"
              v-model="dispatchDialog.productLine.form.productionLineIds"
              @change="handleLineResourceChange"
            ></el-cascader>
          </el-form-item>
          <el-form-item>
            <el-button size="mini" type="primary" :disabled="isReadOnlyDispatch" @click="handleLineResourceSearch">搜索</el-button>
            <el-button size="mini" type="primary" :disabled="isReadOnlyDispatch" @click="handleLineResourceEmpty">清空</el-button>
          </el-form-item>
        </el-form>
        <div class="gannt-menu-button-group">
          <div class="legendList">
            <div class="legendItem"><span class="finished"></span>累计工时占比<90%</div>
            <div class="legendItem"><span class="finishing"></span>90%≤累计工时占比≤100%</div>
            <div class="legendItem"><span class="notFinish"></span>累计工时占比>100%</div>
          </div>
          <div class="sign">资源单位:H</div>
          <div class="sign">资源维度:天</div>
        </div>
      </div>
      <div id="gannt-container" v-loading="ganntLoading">
        <GanttComponent v-if="showGantt" ref="gantt" class="left-container" :tasks="tasks" :readonly="true"></GanttComponent>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" icon="el-icon-circle-close" @click="handleCloseDispatchDialog">关闭</el-button>
        <el-button size="small" type="primary" icon="el-icon-s-promotion" v-if="!isReadOnlyDispatch" @click="handleDispatch" v-preventReClick>提交</el-button>
      </span>
    </el-dialog>

    <WorkorderPlanDetail ref="planDetail" v-if="planDetailVisible" :visible.sync="planDetailVisible"></WorkorderPlanDetail>

    <el-dialog title="撤销排程" custom-class="undoDialog" append-to-body :close-on-click-modal="false" :visible.sync="undoSchedule.visible" @close="$refs.form.resetForm()">
      <avue-form
        ref="form"
        class="workInfoForm"
        v-model="undoSchedule.form"
        :option="undoSchedule.options"
        @submit="handleUndoSubmit"
        @reset-change="handleUndoReset"
      ></avue-form>
      <div class="dispatch-title">
        <div class="dispatch-title-dot"></div>
        <div class="dispatch-title-text">已选中工单</div>
      </div>
      <avue-crud ref="dispatchCrud" :option="undoSchedule.plan.option" :data="undoSchedule.plan.data" @row-del="undoScheduleDel"> </avue-crud>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" icon="el-icon-circle-close" @click="$refs.form.resetForm()">取消</el-button>
        <el-button size="small" type="primary" icon="el-icon-circle-plus-outline" @click="$refs.form.submit()">提交</el-button>
      </span>
    </el-dialog>

    <!-- 导入异常 -->
    <el-dialog width="80%" custom-class="importErrorDialog" title="导入异常" :visible.sync="errorImport.visible" append-to-body :show-close="false">
      <avue-crud
        ref="errorForm"
        v-model="errorImport.form"
        :option="errorImport.option"
        :data="errorImport.data"
        @search-change="searchErrorChange"
        @search-reset="searchErrorReset"
      >
        <!-- <template slot-scope="scope" slot="menu">
          <el-button type="text" size="small" v-if="[3, 4, 5].includes(scope.row.type) && !scope.row.hide" @click.stop="handleErrorTrue(scope.row, scope.index)">是</el-button>
          <el-button type="text" size="small" v-if="[3, 4, 5].includes(scope.row.type) && !scope.row.hide" @click.stop="handleErrorFalse(scope.row, scope.index)">否</el-button>
        </template> -->
      </avue-crud>
      <span slot="footer" class="dialog-footer">
        <!-- <el-button
          size="small"
          v-if="errorImport.allData.find((item) => item.type == 3 || item.type == 4 || item.type == 5)"
          @click="errorReloadImport"
          :disabled="errorImportDisabled"
          >导入</el-button
        > -->
        <el-button size="small" @click="errorImport.visible = false">关闭</el-button>
      </span>
    </el-dialog>

    <!-- 计划导入 -->
    <importDialogComp
      :title="importConfig.title"
      :anotherExportMethod="true"
      :exportCode="importConfig.exportCode"
      :url="importConfig.importUrl"
      :formData="importConfig.formData"
      :export-name="importConfig.exportName"
      :visible.sync="importConfig.show"
      @submit="codeClose"
    ></importDialogComp>
    <export-comp
      ref="exportComp"
      page-api-url="mes-product/workorderPlan/page-workOrder-with-process-and-plan"
      reportCode="workorderPlan_export"
      :option="option"
      :page="page"
      :query="query"
      file-name="计划排程"
    >
    </export-comp>
    <!-- 物料基础数据 弹框 -->
    <common-modal-template ref="commonModalTemplate" :option="tableOption" @getSelectedRows="getSelectedRows" :key="timer" @newKey="newKey"> </common-modal-template>
    <global-modal-template :visibile.sync="visibile" :option="tableOption" @getSelectedRows="getSelectedRows" :key="timer" @newKey="newKey"> </global-modal-template>
  </basic-container>
</template>

<script>
import {
  getList,
  getPlanInfoList,
  submitPlan,
  revokePlan,
  getPlanLineInfo,
  getProductLineSection,
  getLineResourceByProductPart,
  getOperationLog
} from '@/api/product/workOrderPlanAps';
import { templateConfig } from '@/components/common-modal-template/template.js';
import { getList as getCapacityList, capacitySubmit, getDetail as getCapacityDetail, changeUph } from '@/api/product/productStandardCapacity';
import { handleJumpCache } from '@/util/util';
import userTableConfig from '@/components/user-table-config';
import userConfig from '@/mixins/userConfig';
import { getDictionary } from '@/api/system/dictbiz.js';
import { getDay } from '@/views/product/data/workorderPlan';
import request from '@/router/axios';
import { mapGetters, mapState } from 'vuex';

import CommonModalTemplate from '@/components/common-modal-template/common-modal-template.vue';
import GlobalModalTemplate from '@/components/common-modal-template/global-modal-template.vue';
import WorkorderPlanDetail from './components/workorderPlanDetail.vue';
import importDialogComp from '@/components/dialog/import/index.vue';
import GanttComponent from './components/GanttComponent.vue';
import exportComp from '@/components/export-comp';
const fixedColumns = [
  {
    label: '产线',
    prop: 'sectionAndLine',
    headerslot: true,
    align: 'center',
    fixed: true,
    width: 220,
    rules: [
      {
        required: true,
        message: '请输入派工产线',
        trigger: 'blur'
      }
    ]
  },
  {
    label: '优先级',
    prop: 'priority',
    headerslot: true,
    width: 80,
    align: 'center',
    fixed: true
  },
  {
    label: '工段计划数量',
    prop: 'sectionPlanQuantity',
    width: 120,
    align: 'center',
    fixed: true
  },
  {
    label: '产线已排数量',
    prop: 'linePlanQuantity',
    align: 'center',
    fixed: true,
    width: 80
  },
  {
    label: '工段待排数量',
    prop: 'sectionRemainingQuantity',
    align: 'center',
    fixed: true,
    width: 80
  },
  {
    label: 'UPH(每小时产能)',
    prop: 'uph',
    align: 'center',
    fixed: true,
    width: 105
  }
];
export default {
  name: 'workorderPlan',
  components: {
    CommonModalTemplate,
    GlobalModalTemplate,
    userTableConfig,
    GanttComponent,
    exportComp,
    importDialogComp,
    WorkorderPlanDetail
  },
  mixins: [
    userConfig({
      paramKey: {
        isAudit: 'workOrderProcess.isAudit'
      }
    })
  ],
  inject: ['globalStartLoad', 'globalEndLoad'],
  data() {
    return {
      fileParams: {},
      planDetailVisible: false,
      errorImport: {
        visible: false,
        form: {},
        option: {
          height: 'calc(100vh - 486px)',
          calcHeight: 30,
          tip: false,
          searchShow: true,
          searchMenuSpan: 8,
          border: true,
          index: true,
          indexLabel: '序号',
          viewBtn: false,
          editBtn: false,
          addBtn: false,
          delBtn: false,
          refreshBtn: false,
          selection: false,
          dialogClickModal: false,
          menu: false,
          menuWidth: 100,
          dialogDrag: true,
          highlightCurrentRow: true,
          columnBtn: false,
          column: [
            { label: '行号', width: 80, prop: 'code' },
            {
              label: '类型',
              prop: 'type',
              width: 100,
              search: true,
              searchSpan: 8,
              type: 'select',
              dicData: [
                { label: '内容错误', value: '内容错误' },
                { label: '系统配置', value: '系统配置' }
                // { label: '内容重复', value: 3 },
                // { label: '系统重复', value: 4 },
                // { label: '系统提示', value: 5 }
              ]
            },
            { label: '原因', prop: 'value', overHidden: true }
          ]
        },
        data: [],
        allData: []
      },
      importConfig: {
        show: false,
        importUrl: '/api/mes-product/workorderPlan/import',
        exportName: '计划排程导入模版.xlsx',
        formData: {
          req: []
        },
        exportCode: 'WORKORDER_PLAN_IMPORT_TEMPLATE',
        title: '计划排程导入'
      },
      processIsAudit: true,
      originalDispatchPlanData: null, // 原始产线派工计划数据（用于取消时的比较，判断是否有变化）
      oldDispatchPlanData: null, // 旧产线派工计划数据
      isReadOnlyDispatch: false,
      ganntLoading: false,
      showGantt: false,
      backDay: 5,
      backDayList: [
        {
          label: '5天',
          value: 5
        },
        {
          label: '7天',
          value: 7
        },
        {
          label: '14天',
          value: 14
        },
        {
          label: '30天',
          value: 30
        },
        {
          label: '当月',
          value: 'sameMonth'
        },
        {
          label: '下个月',
          value: 'nextMonth'
        }
      ],
      sectionStatusList: [], // 产线状态列表
      productionLineIds: [],
      selectedTask: null,
      tasks: {
        noWorkDates: [],
        initTime: [],
        data: [],
        links: [],
        oldData: [],
        calendarObj: {}
      },
      allLineSection: [],
      productLineSection: [],
      pageCode: 'WORKORDER_PLAN',
      dialogVisible: false,
      partMasterId: '',
      firstToEdit: true,
      visibile: false,
      form: {},
      query: {},
      search: {},
      defaults: {},
      loading: true,
      data: [],
      commonDialog: {
        dispatch: true
      },
      modalName: '', //打开公用模态框名称
      tableOption: {}, //公用模态框配置信息
      timer: new Date().getTime(), //不同内容使用同一个模态框结构，key值不同需要重新请求渲染数据，否则会请求到上一个使用的数据内容
      page: {
        pageSize: 20,
        currentPage: 1,
        total: 0
      },
      // 1：待排程；2：待生产；3：生产中；4：完工；5：锁定；6：强制完工；';
      // workOrderStatus: ['待排程', '待生产', '生产中', '完工', '锁定', '强制完工'],
      selectionList: [],
      option: {
        height: 'calc(100vh - 420px)',
        calcHeight: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        searchMenuPosition: 'right',
        searchLabelWidth: 100,
        border: true,
        index: true,
        indexLabel: '序号',
        viewBtn: false,
        editBtn: false,
        addBtn: false,
        delBtn: false,
        selection: true,
        dialogClickModal: false,
        menu: true,
        menuWidth: 100,
        labelWidth: 160,
        dialogDrag: true,
        highlightCurrentRow: true,
        columnBtn: false,
        column: [
          {
            label: '工单号',
            prop: 'workOrderNo',
            width: 150,
            disabled: true,
            searchOrder: 1,
            search: true,
            overHidden: true,
            rules: [
              {
                required: true,
                message: '请输入工单号',
                trigger: 'blur'
              }
            ]
          },
          {
            label: '产品编码',
            prop: 'productPartNo',
            width: 150,
            search: true,
            searchType: 'input',
            searchOrder: 5,
            type: 'search',
            overHidden: true,
            dicData: [],
            disabled: true,
            placeholder: '请输入 产品编码'
          },
          {
            label: '产品型号',
            prop: 'productPartModel',
            width: 150,
            search: false,
            overHidden: true,
            searchOrder: 6,
            disabled: true,
            rules: [
              {
                required: true,
                message: '请输入产品名称',
                trigger: 'blur'
              }
            ]
          },
          {
            label: '客户编码',
            prop: 'customerCode'
          },
          {
            label: '客户名称',
            prop: 'customerName',
            searchOrder: 2,
            search: true
          },
          {
            label: '工单类型',
            prop: 'type',
            type: 'select',
            width: 100,
            searchOrder: 3,
            search: true,
            multiple: true,
            tags: true,
            value: '1',
            rules: [
              {
                required: true,
                message: '请选择工单类型',
                trigger: 'change'
              }
            ],
            dicUrl: '/api/blade-system/dict/dictionary?code=order_type',
            props: {
              label: 'dictValue',
              value: 'dictKey'
            }
          },
          {
            label: '工单状态',
            prop: 'status',
            searchOrder: 4,
            type: 'select',
            search: true,
            multiple: true,
            tags: true,
            width: 80,
            html: true,
            formatter: (val) => this.$statusText.GD(val.status),
            props: {
              label: 'dictValue',
              value: 'dictKey'
            },
            dicUrl: '/api/blade-system/dict/dictionary?code=mfg_work_order',
            rules: [
              {
                required: true,
                message: '请输入状态',
                trigger: 'blur'
              }
            ]
          },
          {
            label: '工艺路线状态',
            width: 100,
            disabled: true,
            searchOrder: 6,
            prop: 'woProcessStatus',
            type: 'select',
            search: true,
            multiple: true,
            tags: true,
            value: false,
            dicData: [
              {
                label: '未设计',
                value: 1
              },
              {
                label: '待审核',
                value: 2
              },
              {
                label: '已发布',
                value: 3
              }
            ],
            html: true,
            formatter: (val) => this.$statusText.GYLX(val.woProcessStatus)
          },
          {
            label: '工单数量',
            prop: 'planQuantity',
            type: 'number',
            width: 90,
            minRows: 1,
            rules: [
              {
                required: true,
                message: '请输入工单生产数量',
                trigger: 'blur'
              }
            ]
          },
          {
            label: '要求发货时间',
            width: 130,
            prop: 'requiredDeliveryDate'
          },
          {
            label: '计划开始时间',
            prop: 'planStartTime',
            type: 'datetime',
            width: 130,
            format: 'yyyy-MM-dd HH:mm:ss',
            valueFormat: 'yyyy-MM-dd HH:mm:ss'
          },
          {
            label: '计划结束时间',
            prop: 'planEndTime',
            type: 'datetime',
            width: 130,
            format: 'yyyy-MM-dd HH:mm:ss',
            valueFormat: 'yyyy-MM-dd HH:mm:ss'
          },
          {
            label: '排程时间',
            prop: 'planTime',
            type: 'datetimerange',
            width: 130,
            searchOrder: 7,
            search: true,
            searchType: 'datetimerange',
            format: 'yyyy-MM-dd HH:mm:ss',
            valueFormat: 'yyyy-MM-dd HH:mm:ss',
            startPlaceholder: '计划开始时间',
            endPlaceholder: '计划完成时间',
            hide: true,
            defaultTime: ['00:00:00', '23:59:59']
          },
          {
            label: '更新人',
            prop: 'updateUserName',
            width: 80,
            overHidden: true,
            disabled: true
          },
          {
            label: '备注',
            prop: 'remark',
            type: 'textarea',
            width: 100,
            span: 24,
            maxRows: 3,
            minRows: 3,
            maxlength: 300,
            overHidden: true,
            showWordLimit: true
          }
        ]
      },
      productionlineList: [], //产线列表
      dateNonWorkingList: [], //非工作时间列表
      dispatchDialog: {
        workOrderInfo: {
          form: {
            workOrderNo: '',
            productPartNo: '',
            productPartModel: '',
            customerCode: '',
            customerName: '',
            remark: '',
            planQuantity: ''
          },
          options: {
            submitBtn: false,
            emptyBtn: false,
            labelWidth: 80,
            column: [
              {
                label: '工单号',
                prop: 'workOrderNo',
                type: 'search',
                disabled: true,
                span: 6,
                appendClick: () => {
                  this.openUserCommonModal({
                    type: 'workOrder'
                  });
                }
              },
              {
                label: '工单数量',
                prop: 'planQuantity',
                disabled: true,
                span: 6
              },
              {
                label: '产品编码',
                prop: 'productPartNo',
                disabled: true,
                span: 6
              },
              {
                label: '产品型号',
                prop: 'productPartModel',
                disabled: true,
                span: 6
              },
              {
                label: '客户编码',
                prop: 'customerCode',
                disabled: true,
                span: 6
              },
              {
                label: '客户名称',
                prop: 'customerName',
                disabled: true,
                span: 6
              },
              {
                label: '备注',
                prop: 'remark',
                disabled: false,
                span: 12
              }
            ]
          }
        },
        plan: {
          priorityList: [], //优先级列表
          loading: false,
          option: {
            height: '33vh',
            calcHeight: 30,
            tip: false,
            searchShow: true,
            searchMenuSpan: 5,
            searchLabelWidth: 100,
            border: true,
            index: false,
            indexLabel: '序号',
            viewBtn: false,
            editBtn: false,
            addBtn: false,
            delBtn: true,
            refreshBtn: false,
            columnBtn: false,
            addRowBtn: false,
            cancelBtn: false,
            selection: false,
            dialogClickModal: false,
            menu: true,
            menuWidth: 80,
            labelWidth: 160,
            dialogDrag: true,
            highlightCurrentRow: true,
            column: fixedColumns
          },
          data: [
            {
              sectionAndLine: ['', ''],
              priority: '',
              sectionPlanQuantity: undefined,
              uph: undefined,
              linePlanQuantity: '',
              sectionRemainingQuantity: ''
            }
          ]
        },
        productLine: {
          form: {
            productionLineIds: []
          }
        }
      },
      undoSchedule: {
        visible: false,
        form: {},
        options: {
          submitBtn: false,
          emptyBtn: false,
          labelWidth: 100,
          column: [
            {
              label: '撤销原因',
              prop: 'reason',
              span: 24,
              type: 'textarea',
              maxRows: 3,
              minRows: 3,
              maxlength: 300,
              showWordLimit: true,
              rules: [
                {
                  required: true,
                  message: '请输入撤销原因',
                  trigger: 'blur'
                }
              ]
            }
          ]
        },
        plan: {
          loading: false,
          option: {
            height: '300px',
            calcHeight: 30,
            tip: false,
            searchShow: true,
            searchMenuSpan: 5,
            searchLabelWidth: 100,
            border: true,
            index: true,
            indexLabel: '序号',
            viewBtn: false,
            editBtn: false,
            addBtn: false,
            delBtn: true,
            refreshBtn: false,
            columnBtn: false,
            addRowBtn: false,
            cancelBtn: false,
            selection: false,
            dialogClickModal: false,
            menu: true,
            menuWidth: 80,
            labelWidth: 160,
            dialogDrag: true,
            highlightCurrentRow: true,
            column: [
              {
                label: '工单号',
                prop: 'workOrderNo'
              },
              {
                label: '产品编码',
                prop: 'productPartNo'
              },
              {
                label: '产品型号',
                prop: 'productPartModel'
              },
              {
                label: '工单数量',
                prop: 'planQuantity'
              }
            ]
          },
          data: []
        }
      }
    };
  },
  watch: {
    'dispatchDialog.plan.data': {
      handler(value) {
        const that = this;
        let validData = that.mergeBySectionId(value.filter((item) => item.sectionId));
        // planStatus 1:未排 2:排程中 3:已排完
        that.sectionStatusList.forEach((statusList) => {
          statusList.planStatus = statusList.originPlanStatus;
        });
        validData.forEach((item) => {
          that.sectionStatusList.forEach((statusList) => {
            if (statusList.sectionId == item.sectionId) {
              if (parseInt(item.sectionRemainingQuantity) <= 0) {
                statusList.planStatus = 3;
              } else {
                statusList.planStatus = 2;
              }
            }
          });
        });
      },
      deep: true
    }
  },
  computed: {
    ...mapGetters(['permission']),
    ...mapState({
      realName: (state) => state.user.userInfo.real_name,
      userId: (state) => state.user.userInfo.user_id
    }),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.workorder_add, false),
        viewBtn: this.vaildData(this.permission.workorder_view, false),
        delBtn: this.vaildData(this.permission.workorder_delete, false),
        editBtn: this.vaildData(this.permission.workorder_edit, false)
      };
    },
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(',');
    },
    dateColumns() {
      let dates = [];
      this.dispatchDialog.plan.option.column.slice(fixedColumns.length).map((month) => {
        month.children.map((day) => {
          dates.push({
            date: day.prop,
            isWorkday: month.isWorkday
          });
        });
      });
      return dates;
    },
    // 非生产日集合
    noWorkDates() {
      return [
        ...new Set(
          this.dispatchDialog.plan.option.column
            .slice(fixedColumns.length)
            .filter((d) => !d.isWorkday)
            .map((d) => d.prop)
        )
      ];
    },
    errorImportDisabled() {
      return this.errorImport.allData.some((item) => !item.hide);
    },
    isSelectEnter() {
      if (this.selectionList && this.selectionList.length > 0) {
        return true;
      } else {
        return false;
      }
    },
    selectOrderId() {
      if (this.dispatchDialog.workOrderInfo.form.orderId) {
        return this.dispatchDialog.workOrderInfo.form.orderId;
      } else if (this.selectionList && this.selectionList.length > 0) {
        return this.selectionList[0].id;
      }
    },
    disabledDispatch() {
      if (this.selectionList && this.selectionList.length > 1) {
        return true;
      } else {
        return false;
      }
    },
    disabledWithdraw() {
      return this.selectionList.length == 0;
    },
    // 未排
    notDispatchSectionList() {
      return this.sectionStatusList.filter((item) => item.planStatus == 1).map((s) => s.sectionName);
    },
    // 排程中
    dispatchIngSectionList() {
      return this.sectionStatusList.filter((item) => item.planStatus == 2).map((s) => s.sectionName);
    },
    // 已排完
    dispatchedSectionList() {
      return this.sectionStatusList.filter((item) => item.planStatus == 3).map((s) => s.sectionName);
    },
    isWorkday(planDateInfoList, date) {
      return (planDateInfoList, date) => {
        if (planDateInfoList && planDateInfoList.length > 0) {
          let obj = planDateInfoList.find((p) => p.dayPlanDate == date.split(':')[0]);
          return obj ? obj.isWorkday : false;
        } else {
          return false;
        }
      };
    }
  },
  mounted() {
    getDictionary({ code: 'PRIORITY' }).then((res) => {
      if (res && res.status == 200) {
        this.dispatchDialog.plan.priorityList = res.data.data.map((d) => {
          return {
            label: d.dictValue,
            value: Number(d.dictKey)
          };
        });
      }
    });
    this.$nextTick(() => {
      //搜索与表格结构分隔
      this.$structuralSplit();
    });
  },
  activated() {},
  beforeRouteEnter(to, from, next) {
    handleJumpCache(this, next, from, '/product/workorder');
  },
  methods: {
    onLoad(page, params = {}) {
      this.loading = true;
      getList(page.currentPage, page.pageSize, Object.assign(params, this.query))
        .then((res) => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.selectionClear();
        })
        .finally(() => {
          this.loading = false;
        });
    },
    mergeBySectionId(array) {
      const merged = {};

      array.forEach((item) => {
        if (!merged[item.sectionId]) {
          merged[item.sectionId] = { ...item };
        }
      });

      // 将合并后的对象转换回数组
      return Object.values(merged);
    },
    // 派工 撤回
    handleMenu(params) {
      let { type } = params;
      if (type == 'dispatch' && this.selectionList.length === 0) {
        this.isReadOnlyDispatch = true;
        this.dispatchDialog.workOrderInfo.form.workOrderNo = '';
        this.dispatchDialog.workOrderInfo.form.planQuantity = '';
        this.dispatchDialog.workOrderInfo.form.productPartNo = '';
        this.dispatchDialog.workOrderInfo.form.productPartModel = '';
        this.dispatchDialog.workOrderInfo.form.productPartId = '';
        this.dispatchDialog.workOrderInfo.form.customerCode = '';
        this.dispatchDialog.workOrderInfo.form.customerName = '';
        this.dispatchDialog.workOrderInfo.form.remark = '';
        this.sectionStatusList = [];
        this.dispatchDialog.plan.option.column = fixedColumns;
        this.dispatchDialog.plan.data = [
          {
            sectionAndLine: ['', ''],
            priority: '',
            sectionPlanQuantity: undefined,
            uph: undefined,
            linePlanQuantity: '',
            sectionRemainingQuantity: ''
          }
        ];
        this.ganntLoading = true;
        this.dialogVisible = true;
        // 1.获取工段产线列表;
        this.handleGetProductLineSection();
        setTimeout(() => {
          this.handleSetDateColums();
          this.ganntLoading = false;
          this.showGantt = true;
        });
        return false;
      }

      // 工单生产中，无法编辑工艺路线
      //  1：待排程；2：待生产；3：生产中；4：完工；5：锁定；6：强制完工;
      if (type == 'dispatch' && this.selectionList.length === 1) {
        // 工单状态为 完工、锁定、强制完工 => 只能查看
        this.isReadOnlyDispatch = this.selectionList.every((s) => s.status == 4 || s.status == 5 || s.status == 6);
        if (this.selectionList[0].woProcessStatus == 1) {
          this.$message.warning('该工单工艺路线未设计，无法派工');
          return;
        }
        // if (this.selectionList[0].woProcessStatus == 2) {
        //   this.$message.warning('该工单工艺路线待审核，无法派工');
        //   return;
        // }
        this.dispatchDialog.workOrderInfo.form.workOrderNo = this.selectionList[0].workOrderNo;
        this.dispatchDialog.workOrderInfo.form.planQuantity = this.selectionList[0].planQuantity;
        this.dispatchDialog.workOrderInfo.form.productPartNo = this.selectionList[0].productPartNo;
        this.dispatchDialog.workOrderInfo.form.productPartModel = this.selectionList[0].productPartModel;
        this.dispatchDialog.workOrderInfo.form.productPartId = this.selectionList[0].productPartId;
        this.dispatchDialog.workOrderInfo.form.customerCode = this.selectionList[0].customerCode;
        this.dispatchDialog.workOrderInfo.form.customerName = this.selectionList[0].customerName;
        this.dispatchDialog.workOrderInfo.form.remark = '';
        this.sectionStatusList = [];
        this.dispatchDialog.plan.option.column = fixedColumns;
        console.log(this.dispatchDialog.plan.option.column);
        this.dispatchDialog.plan.data = [
          {
            sectionAndLine: ['', ''],
            priority: '',
            sectionPlanQuantity: undefined,
            uph: undefined,
            linePlanQuantity: '',
            sectionRemainingQuantity: ''
          }
        ];
        this.ganntLoading = true;
        this.dialogVisible = true;
        // 1.获取工段产线列表;
        this.handleGetProductLineSection();
        setTimeout(() => {
          Promise.all([
            // 2.获取产线资源数据
            this.handleGetAllApsResource(this.selectionList[0].productPartId),
            // 3.获取产线派工列表信息;
            this.handleGetLineDispatchList(this.selectionList[0].id),
            // 4.获取排程备注
            this.handleGetDispatchRemark(this.selectionList[0].workOrderNo)
          ]);
        }, 200);
        return;
      }
      if (type == 'revoke') {
        // 只有待生产才能进行撤回
        let status = this.selectionList.every((s) => s.status == 2);
        if (!status) {
          this.$message.warning('只有待生产状态才能进行撤销排程');
          return;
        }
        this.undoSchedule.plan.data = structuredClone(this.selectionList);
        this.undoSchedule.visible = true;
        return;
      }
    },
    handleGetQueryTime() {
      let queryTimeStart = this.$moment().format('YYYY-MM-DD 00:00:00');
      let queryTimeEnd = this.$moment()
        .add(this.backDay - 1, 'days')
        .format('YYYY-MM-DD 23:59:59');
      if (this.backDay == 'sameMonth') {
        queryTimeStart = this.$moment().startOf('month').format('YYYY-MM-DD 00:00:00');
        queryTimeEnd = this.$moment().endOf('month').format('YYYY-MM-DD 23:59:59');
      } else if (this.backDay == 'nextMonth') {
        queryTimeStart = this.$moment().startOf('month').subtract('month', -1).format('YYYY-MM-DD 00:00:00');
        queryTimeEnd = this.$moment().endOf('month').subtract('month', -1).format('YYYY-MM-DD 23:59:59');
      }
      return { queryTimeStart, queryTimeEnd };
    },
    async handleGetDispatchRemark(workOrderNo) {
      let data = await getOperationLog(workOrderNo);
      if (data.data.code == 200 && data.data.data) {
        this.dispatchDialog.workOrderInfo.form.remark = data.data.data.remark;
      } else {
        this.dispatchDialog.workOrderInfo.form.remark = '';
      }
    },
    // 获取产线派工列表
    handleGetLineDispatchList(workOrderId) {
      console.log(this.backDay);
      this.dispatchDialog.plan.loading = true;
      let { queryTimeStart, queryTimeEnd } = this.handleGetQueryTime();
      getPlanInfoList({ workOrderId, queryTimeStart, queryTimeEnd })
        .then((res) => {
          let data = res.data.data;
          this.dateNonWorkingList = data.dateNonWorkingList;
          this.sectionStatusList = data.sectionStatusList.map((item) => {
            return {
              ...item,
              originPlanStatus: item.planStatus
            };
          });
          if (this.sectionStatusList && this.sectionStatusList.length > 0) {
            let reallySectionList = this.allLineSection.filter((all) => {
              return this.sectionStatusList.map((sItem) => sItem.sectionId).includes(all.value);
            });
            this.productLineSection = reallySectionList;
            console.log(this.productLineSection, 'this.productLineSection');
          }
          if (data.planLineInfoVoList && data.planLineInfoVoList.length > 0) {
            data.planLineInfoVoList.forEach((item) => {
              item.sectionAndLine = [item.sectionId, item.lineId];
              let sectionNoWorkList = data.dateNonWorkingList.find((obj) => obj.sectionId === item.sectionId);
              if (item.planDateInfoList && item.planDateInfoList.length > 0) {
                item.planDateInfoList.forEach((dateItem) => {
                  dateItem.isWorkday = false;
                  item[dateItem.dayPlanDate + ':dayPlanQuantity'] = dateItem.dayPlanQuantity;
                  item[dateItem.dayPlanDate + ':dayPlanWorkHour'] = dateItem.dayPlanWorkHour || 0;
                  item[dateItem.dayPlanDate + ':dayRemainingWorkHourOfLine'] = dateItem.dayRemainingWorkHourOfLine || 0;
                  if (sectionNoWorkList && sectionNoWorkList.nonWorkingDayList && sectionNoWorkList.nonWorkingDayList.length > 0) {
                    sectionNoWorkList.nonWorkingDayList.forEach((dateObj) => {
                      if (dateObj === dateItem.dayPlanDate) {
                        dateItem.isWorkday = true;
                      }
                    });
                  }
                });
              }
            });
          }
          this.dispatchDialog.plan.data =
            data.planLineInfoVoList.length > 0
              ? data.planLineInfoVoList
              : [
                  {
                    sectionAndLine: ['', ''],
                    priority: '',
                    sectionPlanQuantity: undefined,
                    uph: undefined,
                    linePlanQuantity: '',
                    sectionRemainingQuantity: '',
                    planDateInfoList: []
                  }
                ];
          console.log(this.dispatchDialog.plan.data, 'this.dispatchDialog.plan.data');
          this.handleSetDateColums();
        })
        .finally(() => {
          this.dispatchDialog.plan.loading = false;
        });
    },
    handleSetDateColums() {
      let dateColums = getDay(this.backDay).map((item, index) => {
        let [date, week] = item.split(':');
        return {
          prop: date,
          label: date + '(' + week + ')',
          align: 'center',
          isWorkday: 0,
          children: [
            {
              label: '剩余工时',
              prop: date + ':dayRemainingWorkHourOfLine',
              width: 60,
              align: 'center'
            },
            {
              label: '计划数量',
              prop: date + ':dayPlanQuantity',
              width: 105,
              align: 'center'
            },
            {
              label: '计划工时',
              prop: date + ':dayPlanWorkHour',
              width: 60,
              align: 'center'
            }
          ]
        };
      });
      console.log(dateColums, 'dateColums');
      this.dispatchDialog.plan.option.column = fixedColumns.concat(dateColums);
      this.$refs.dispatchCrud.refreshTable();
    },
    openUserCommonModal(params) {
      let { type } = params;
      switch (type) {
        // 生产订单
        case 'workOrder':
          // 查询条件 只查找待审核和已发布工艺路线的工单
          let query = {
            woProcessStatusStr: '2,3'
          };
          this.tableOption = {
            modalTitle: '选择工单信息（双击进行选择）',
            url: '/api/mes-product/workorderPlan/page-workOrder-with-process-and-plan',
            isPage: true,
            index: true,
            indexLabel: '序号',
            rowSelectionType: 'single',
            titleInfo: 'workOrderModal',
            query,
            columnDefs: templateConfig.WORKORDERPLAN
          };
          this.$refs.commonModalTemplate.showModal();
          break;
        default:
          break;
      }
    },
    // 获取选择的物料模态框行数据
    getSelectedRows(rowData, titleInfo) {
      switch (titleInfo) {
        case 'workOrderModal':
          if (rowData.woProcessStatus == 1) {
            this.$message.warning('该工单工艺路线未设计，无法派工');
            return;
          }
          // 工单状态为 完工、锁定、强制完工 => 只能查看
          this.isReadOnlyDispatch = rowData.status == 4 || rowData.status == 5 || rowData.status == 6;

          this.dispatchDialog.workOrderInfo.form.orderId = rowData.id;
          this.dispatchDialog.workOrderInfo.form.workOrderNo = rowData.workOrderNo;
          this.dispatchDialog.workOrderInfo.form.productPartNo = rowData.productPartNo;
          this.dispatchDialog.workOrderInfo.form.productPartModel = rowData.productPartModel;
          this.dispatchDialog.workOrderInfo.form.productPartName = rowData.productPartName;
          this.dispatchDialog.workOrderInfo.form.productPartId = rowData.productPartId;
          this.dispatchDialog.workOrderInfo.form.planQuantity = rowData.planQuantity;
          this.dispatchDialog.workOrderInfo.form.remark = rowData.remark;
          this.dispatchDialog.workOrderInfo.form.customerCode = rowData.customerCode;
          this.dispatchDialog.workOrderInfo.form.customerName = rowData.customerName;
          this.dispatchDialog.workOrderInfo.form.isSave = false;
          Promise.all([
            // 1.获取产线派工列表信息;
            this.handleGetLineDispatchList(rowData.id),
            // 2.获取产线资源数据
            this.handleGetAllApsResource(rowData.productPartId),
            // 3.获取产线派工列表信息;
            this.handleGetLineDispatchList(rowData.id),
            // 4.获取排程备注
            this.handleGetDispatchRemark(rowData.workOrderNo)
          ]);

          break;
        default:
          break;
      }
    },
    rowClick(row, column) {
      this.$util.table.rowClick(this.$refs.crud, row, this.selectionList);
    },
    handSelect() {
      this.$refs.crud.setCurrentRow();
    },
    selectionAll() {
      this.$refs.crud.setCurrentRow();
    },
    addRow() {
      if (this.isReadOnlyDispatch) {
        return false;
      }
      let dataCheck = this.dispatchDialog.plan.data.find((d) => {
        return !d.priority || !d.sectionPlanQuantity;
      });
      if (dataCheck) {
        console.log(dataCheck);
        this.$message.warning('工段计划数量和优先级不能为空，请仔细检查');
        return;
      }
      this.dispatchDialog.plan.data.push({
        sectionAndLine: ['', ''],
        priority: '',
        sectionPlanQuantity: undefined,
        uph: undefined,
        linePlanQuantity: '',
        sectionRemainingQuantity: ''
      });
      this.$util.table.elTableScrollTorow(this.$refs.dispatchCrud, this.dispatchDialog.plan.data.length, 4);
    },
    dispatchPlanDel(row) {
      if (this.isReadOnlyDispatch) {
        return false;
      }
      this.$confirm('确定将选择数据删除?', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        if (this.dispatchDialog.plan.data.length == 1) {
          this.dispatchDialog.plan.data = [
            {
              sectionAndLine: ['', ''],
              priority: '',
              sectionPlanQuantity: undefined,
              uph: undefined,
              linePlanQuantity: '',
              sectionRemainingQuantity: ''
            }
          ];
        } else {
          let index = row.$index;
          this.dispatchDialog.plan.data.splice(index, 1);
          // 检测有没有其它相同工段
          let currentSectionId = row.sectionId;
          let sameSectionIdData = this.dispatchDialog.plan.data.filter((item) => item.sectionAndLine[0] == currentSectionId);
          if (sameSectionIdData && sameSectionIdData.length > 0) {
            let linePlanQuantitySum = sameSectionIdData.reduce((sum, item) => sum + Number(item.linePlanQuantity || 0), 0);
            sameSectionIdData.forEach((item) => {
              item.sectionRemainingQuantity = Number(row.sectionPlanQuantity) - Number(linePlanQuantitySum);
            });
          }
        }
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      });
    },
    // 获取工段产线列表
    handleGetProductLineSection() {
      this.dispatchDialog.plan.loading = true;
      getProductLineSection()
        .then((res) => {
          let data = res.data.data;
          let allLineSection = data.map((d) => {
            let item = {
              label: d.name,
              value: d.id,
              code: d.code,
              productWorkSectionId: d.productWorkSectionId,
              hasChildren: d.lineList && d.lineList.length > 0 ? true : false
            };
            if (d.lineList && d.lineList.length > 0) {
              item.children = d.lineList.map((l) => {
                return {
                  label: l.lineName,
                  value: l.lineId,
                  code: l.lineCode
                };
              });
            }
            return item;
          });
          this.allLineSection = allLineSection;
          console.log(allLineSection, 'allLineSection');
        })
        .finally(() => {
          this.dispatchDialog.plan.loading = false;
        });
    },
    // 获取aps所有资源列表
    handleGetAllApsResource(productPartId, lineId = '') {
      const that = this;
      let { queryTimeStart, queryTimeEnd } = this.handleGetQueryTime();
      that.ganntLoading = true;
      that.tasks.initTime = [queryTimeStart, queryTimeEnd];
      getLineResourceByProductPart(productPartId, lineId, queryTimeStart, queryTimeEnd)
        .then((res) => {
          let data = res.data.data;
          let dateNonWorkingList = data.dateNonWorkingList;
          let dateRangeArr = getDay(that.backDay).map((d) => d.split(':')[0]);
          let result = [];
          data.sectionList.map((section) => {
            section.lineList.map((line) => {
              result.push({
                id: section.sectionId + line.lineId,
                type: 'project',
                render: 'split',
                text: section.sectionName + '/' + line.lineName,
                openLineDuration: line.openLineDuration,
                clearLineDuration: line.clearLineDuration,
                uph: line.uph
              });
              let dateCodeList = line.dateCodeList.map((item) => item.dateCode);
              dateRangeArr.map((dRange) => {
                if (dateCodeList.includes(dRange)) {
                  if (line.dateCodeList && line.dateCodeList.length > 0) {
                    // 遍历有数据的日期
                    line.dateCodeList.map((date) => {
                      let isNoWorkday = that.handleIsNoWorkday(dateNonWorkingList, date.dateCode, section.sectionId);
                      result.push({
                        id: date.id,
                        date: date.dateCode,
                        isNoWorkday: isNoWorkday,
                        parent: section.sectionId + line.lineId,
                        text: date.workHourAccumulate,
                        progress: Number(date.workHourAccumulatePercent) / 100,
                        start_date: date.dateCode,
                        workHourAccumulate: date.workHourAccumulate,
                        remainingWorkHour: date.remainingWorkHour,
                        workHourAccumulatePercent: date.workHourAccumulatePercent,
                        duration: 24,
                        detailData: date.detailData
                      });
                    });
                  }
                } else {
                  let find = dateNonWorkingList.find((item) => item.sectionId === section.sectionId);
                  if (find) {
                    find.nonWorkingDayList.map((d) => {
                      result.push({
                        id: find.sectionId + line.lineId + d,
                        date: d,
                        isNoWorkday: true,
                        parent: section.sectionId + line.lineId,
                        text: '',
                        progress: 0,
                        start_date: d,
                        workHourAccumulate: '',
                        remainingWorkHour: '',
                        workHourAccumulatePercent: 0,
                        duration: 24,
                        detailData: []
                      });
                    });
                  }
                }
              });
            });
          });
          console.log(result);
          that.tasks.data = result;
          setTimeout(() => {
            that.$refs.gantt && that.$refs.gantt.drawGantt();
          });
        })
        .finally(() => {
          that.ganntLoading = false;
          that.showGantt = true;
        });
    },
    handleIsNoWorkday(dateNonWorkingList, date, sectionId) {
      if (!dateNonWorkingList || dateNonWorkingList.length === 0) {
        // 如果没有非工作日列表或列表为空，则默认不是非工作日
        return false;
      }
      // 使用 find 查找匹配的 sectionId
      const section = dateNonWorkingList.find((dateObj) => dateObj.sectionId === sectionId);
      if (section) {
        // 如果找到了匹配的 sectionId，检查 date 是否在非工作日列表中
        return section.nonWorkingDayList.includes(date);
      }
      // 如果没有找到匹配的 sectionId，则默认不是非工作日
      return false;
    },
    //  工段计划数量
    handleCalculateType1(row, index) {
      console.log(row, index);
      // 检测有没有其它相同工段
      let currentSectionId = row.sectionId;
      let sameSectionIdData = this.dispatchDialog.plan.data.filter((item) => item.sectionAndLine[0] == currentSectionId);
      if (sameSectionIdData && sameSectionIdData.length > 1) {
        // 相同工段产线已排数量之和
        let linePlanQuantitySum = sameSectionIdData.reduce((sum, item) => sum + Number(item.linePlanQuantity || 0), 0);

        sameSectionIdData.forEach((item) => {
          item.sectionPlanQuantity = row.sectionPlanQuantity;
          item.sectionRemainingQuantity = (row.sectionPlanQuantity || 0) - linePlanQuantitySum;
        });
      } else {
        row.sectionRemainingQuantity = Number(row.sectionPlanQuantity || 0) - Number(row.linePlanQuantity || 0);
      }
    },
    // uph
    async handleCalculateType2(row, index) {
      const that = this;
      console.log(row, index);
      if (row.uph) {
        Object.keys(row).forEach((key) => {
          if (key.indexOf(':dayPlanQuantity') > -1 && row[key] > 0) {
            let dayPlanWorkHourKey = key.split(':')[0] + ':dayPlanWorkHour';
            let dayPlanWorkHour = Number(row[key] / row.uph).toFixed(2);
            that.$set(that.dispatchDialog.plan.data[index], dayPlanWorkHourKey, dayPlanWorkHour);
            that.$forceUpdate();
          }
        });
        try {
          let result = await changeUph({
            partMasterId: that.dispatchDialog.workOrderInfo.form.productPartId,
            sectionId: row.sectionId,
            lineId: row.lineId,
            uph: row.uph
          });
          if (result.data.code == 200) {
            that.$message.success(`${that.dispatchDialog.workOrderInfo.form.productPartNo}UPH更新成功`);
          }
        } catch (error) {
          console.log(error);
        }
      }
    },
    // 日产量
    handleCalculateType3(row, index, key) {
      const that = this;
      if (!row.sectionPlanQuantity) {
        that.$message.warning('请输入工段计划数量');
        return;
      }
      if (!row.uph) {
        that.$message.warning('请输入UPH');
        return;
      }
      console.log(row, index, key);

      let date = key.split(':')[0];
      let dayPlanWorkHourKey = date + ':dayPlanWorkHour';
      // 当日计划工时
      let dayPlanWorkHour = Number((row[key] || 0) / row.uph).toFixed(2);
      let dayRemainingWorkHourOfLineKey = date + ':dayRemainingWorkHourOfLine';
      // 当日剩余工时
      let dayRemainingWorkHourOfLine = row[dayRemainingWorkHourOfLineKey];
      // 检测当日计划工时是否超过剩余工时
      if (dayRemainingWorkHourOfLine && Number(dayRemainingWorkHourOfLine) < Number(dayPlanWorkHour)) {
        this.$confirm(`${date}当天的剩余工时为${dayRemainingWorkHourOfLine}，本次排程的计划工时已超过工作时长，请确认是否排程?`, {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            handleRowData();
          })
          .catch(() => {
            row[key]--;
          });
      } else {
        handleRowData();
      }
      function handleRowData() {
        row.linePlanQuantity = Object.keys(row).reduce((pre, cur) => {
          if (cur.indexOf(':dayPlanQuantity') > -1 && row[cur]) {
            pre += Number(row[cur]);
          }
          return pre;
        }, 0);
        that.$set(that.dispatchDialog.plan.data[index], dayPlanWorkHourKey, dayPlanWorkHour);
        that.$forceUpdate();
        // 检测有没有其它相同工段
        let currentSectionId = row.sectionId;
        let sameSectionIdData = that.dispatchDialog.plan.data.filter((item) => item.sectionAndLine[0] == currentSectionId);
        if (sameSectionIdData && sameSectionIdData.length > 1) {
          let linePlanQuantitySum = sameSectionIdData.reduce((sum, item) => sum + Number(item.linePlanQuantity || 0), 0);
          sameSectionIdData.forEach((item) => {
            item.sectionRemainingQuantity = Number(row.sectionPlanQuantity) - Number(linePlanQuantitySum);
          });
        } else {
          row.sectionRemainingQuantity = Number(row.sectionPlanQuantity) - Number(row.linePlanQuantity);
        }
      }
    },
    handleEmptyRowData(row) {
      row.priority = '';
      row.sectionPlanQuantity = undefined;
      row.uph = undefined;
      row.linePlanQuantity = undefined;
      row.sectionRemainingQuantity = undefined;
      for (const key in row) {
        if (key.endsWith(':dayRemainingWorkHourOfLine') || key.endsWith(':dayPlanQuantity') || key.endsWith(':dayPlanWorkHour')) {
          row[key] = undefined;
        }
      }
    },
    // 产线派工产线 切换产线
    handleLineChange(value, row, index) {
      console.log(value, row, index);
      // 检测此工段下是否有产线
      if (!value[1]) {
        this.handleEmptyRowData(row);
        delete row.planDateInfoList;
        return;
      }
      // 检测有没有其它相同产线
      let sameLineIdData = this.dispatchDialog.plan.data.filter((item) => item.sectionAndLine[0] == value[0] && item.sectionAndLine[1] == value[1]);
      if (sameLineIdData && sameLineIdData.length > 1) {
        row.sectionAndLine = ['', ''];
        this.handleEmptyRowData(row);
        this.$message.warning('该产线已存在，请选择其它产线');
        return;
      }
      let rowData = structuredClone(this.dispatchDialog.plan.data[index]);
      rowData.id = '';
      rowData.sectionPlanQuantity = undefined;
      rowData.linePlanQuantity = undefined;
      rowData.sectionRemainingQuantity = undefined;
      rowData.uph = undefined;
      rowData.planDateInfoList = [];
      for (const key in rowData) {
        if (key.endsWith(':dayRemainingWorkHourOfLine') || key.endsWith(':dayPlanQuantity') || key.endsWith(':dayPlanWorkHour')) {
          rowData[key] = undefined;
        }
      }
      let { queryTimeStart, queryTimeEnd } = this.handleGetQueryTime();
      let dateRangeArr = getDay(this.backDay).map((d) => d.split(':')[0]);
      console.log(dateRangeArr, 'dateRangeArr(dateRangeArr.dateRangeArr)');
      getPlanLineInfo(this.dispatchDialog.workOrderInfo.form.productPartId, value[1], queryTimeStart, queryTimeEnd)
        .then((res) => {
          let data = res.data.data;
          console.log(this.dateNonWorkingList, 'this.dateNonWorkingList ');
          rowData.uph = data.uph || undefined;
          rowData.lineName = data.lineName;
          rowData.lineId = data.lineId;
          rowData.sectionId = row.sectionAndLine[0];
          dateRangeArr.forEach((date) => {
            rowData[date + ':dayPlanQuantity'] = undefined;
            rowData[date + ':dayPlanWorkHour'] = undefined;
            rowData[date + ':dayRemainingWorkHourOfLine'] = undefined;
            let planDateInfoList = data.planDateInfoList.map((item) => item.dayPlanDate);
            if (planDateInfoList.includes(date)) {
              if (data.planDateInfoList && data.planDateInfoList.length > 0) {
                data.planDateInfoList.forEach((dateItem) => {
                  if (date == dateItem.dayPlanDate) {
                    dateItem.isWorkday = false;
                    rowData[dateItem.dayPlanDate + ':dayPlanQuantity'] = dateItem.dayPlanQuantity || undefined;
                    rowData[dateItem.dayPlanDate + ':dayPlanWorkHour'] = dateItem.dayPlanWorkHour || 0;
                    rowData[dateItem.dayPlanDate + ':dayRemainingWorkHourOfLine'] = dateItem.dayRemainingWorkHourOfLine || 0;
                    if (this.dateNonWorkingList && this.dateNonWorkingList.length > 0) {
                      this.dateNonWorkingList.forEach((dateObj) => {
                        if (dateObj.sectionId == rowData.sectionId) {
                          if (dateObj.nonWorkingDayList.includes(dateItem.dayPlanDate)) {
                            dateItem.isWorkday = true;
                          }
                        }
                      });
                    }
                  }
                });
              }
            } else {
              // 如果日期不在列表data.planDateInfoList中，则添加到列表中置为非作业日
              data.planDateInfoList = data.planDateInfoList.concat({
                dayPlanDate: date,
                dayPlanQuantity: undefined,
                dayPlanWorkHour: undefined,
                dayRemainingWorkHourOfLine: undefined,
                isWorkday: true
              });
            }
          });
          rowData.planDateInfoList = data.planDateInfoList;
          console.log('rowData', rowData);
          this.$set(this.dispatchDialog.plan.data, index, rowData);

          // 检测有没有其它相同工段
          let currentSectionId = value[0];
          let sameSectionIdData = this.dispatchDialog.plan.data.filter((item) => item.sectionAndLine[0] == currentSectionId);
          if (sameSectionIdData && sameSectionIdData.length > 1) {
            let data = sameSectionIdData.find((item) => item.sectionPlanQuantity && item.sectionRemainingQuantity);
            if (data) {
              sameSectionIdData.forEach((item) => {
                item.sectionPlanQuantity = data.sectionPlanQuantity;
                item.sectionRemainingQuantity = data.sectionRemainingQuantity;
              });
            }
          }
          this.$forceUpdate();
        })
        .catch(() => {});
    },
    // 产线资源 切换产线
    handleLineResourceChange(value) {},
    // 产线资源 搜索
    handleLineResourceSearch() {
      this.productionLineIds = this.$util.util.filterArray(this.dispatchDialog.productLine.form.productionLineIds);
      this.handleGetAllApsResource(this.selectionList[0].productPartId, this.productionLineIds[1]);
    },
    // 产线资源 清空
    handleLineResourceEmpty() {
      this.dispatchDialog.productLine.form.productionLineIds = [];
      this.productionLineIds = [];
      this.handleGetAllApsResource(this.selectionList[0].productPartId, '');
    },
    handleChangeBackDay(value) {
      this.handleGetLineDispatchList(this.selectionList[0].id);
      this.handleGetAllApsResource(this.selectionList[0].productPartId);
    },
    handleDispatch() {
      const that = this;
      let workorderPlanList = that.dispatchDialog.plan.data
        .filter((d) => d.lineId)
        .map((d) => {
          d.planDateDetailList = [];
          for (const key in d) {
            if (key.endsWith(':dayPlanQuantity') && Number(d[key]) > 0) {
              let date = key.split(':')[0];
              d.planDateDetailList.push({
                dayPlanDate: date,
                dayPlanQuantity: d[key],
                dayPlanWorkHour: d[date + ':dayPlanWorkHour']
              });
            }
          }
          return {
            lineId: d.lineId,
            sectionId: d.sectionId,
            priority: d.priority, // 优先级
            sectionPlanQuantity: d.sectionPlanQuantity,
            linePlanQuantity: d.linePlanQuantity,
            sectionRemainingQuantity: Number(d.sectionRemainingQuantity),
            uph: d.uph,
            planDateDetailList: d.planDateDetailList
          };
        });
      console.log(workorderPlanList, 'workorderPlanList');
      if (workorderPlanList.length == 0) {
        this.$message.warning('产线派工计划为空，不可派工!');
        return false;
      }
      // 检测工段待排数量是否出现负数
      for (let i = 0; i < workorderPlanList.length; i++) {
        if (workorderPlanList[i].sectionRemainingQuantity < 0) {
          this.$message.warning('累计的派工计划数量已超过工段待计划，请修改工段计划数量或日期的计划数量！');
          return false;
        }
      }
      submitPlan({
        workOrderId: that.selectOrderId,
        isSkipFeedSectionCheck: false,
        workorderPlanList,
        remark: this.dispatchDialog.workOrderInfo.form.remark
      })
        .then((res) => {
          let data = res.data;
          if (data && !data.data) that.handleDispatchSuccess();
          if (data && data.data && data.data.continueFlagProp) {
            that
              .$confirm(data.msg, '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              })
              .then(() => {
                submitPlan({
                  workOrderId: that.selectOrderId,
                  isSkipFeedSectionCheck: false,
                  workorderPlanList,
                  isSkipLackSectionCheck: true,
                  remark: this.dispatchDialog.workOrderInfo.form.remark
                }).then(() => {
                  that.handleDispatchSuccess();
                });
              })
              .catch(() => {});
          }
        })
        .catch(() => {});
    },
    handleDispatchSuccess() {
      const that = this;
      that.$message({
        type: 'success',
        message: `派工成功!`
      });
      that.dialogVisible = false;
      that.onLoad(that.page);
      that.$refs.crud && that.$refs.crud.toggleSelection();
    },
    handleCloseDispatchDialog() {
      const that = this;
      let oldData = structuredClone(that.originalDispatchPlanData); // 用于判断是否有变化
      let newData = structuredClone(that.dispatchDialog.plan.data);
      let modifyStatus = that.$util.gantt.isModifyDispatch(oldData, newData);
      // 未修改直接关闭
      if (!modifyStatus) {
        that.clearDiapatchData();
      } else {
        that
          .$confirm('是否确认关闭当前页，并放弃本次编辑内容？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          })
          .then(() => {
            that.clearDiapatchData();
          })
          .catch(() => {});
      }
    },
    clearDiapatchData() {
      const that = this;
      console.log('clearDiapatchData');
      that.$refs.gantt && that.$refs.gantt.destroyGantt();
      that.backDay = 5;
      that.dispatchDialog.workOrderInfo.form.orderNo = '';
      that.dispatchDialog.workOrderInfo.form.orderId = '';
      that.dispatchDialog.workOrderInfo.form.isSave = false;
      that.dispatchDialog.plan.data = [];
      that.oldDispatchPlanData = null;
      that.originalDispatchPlanData = null;
      that.tasks.data = [];
      that.tasks.oldData = structuredClone(that.tasks.data);
      that.dialogVisible = false;
      that.showGantt = false;
      that.$refs.crud && that.$refs.crud.toggleSelection();

      let gantt_tooltip = document.querySelector('.gantt_tooltip');
      if (gantt_tooltip) {
        document.body.removeChild(gantt_tooltip);
      }
    },
    handleImport() {
      this.importConfig.show = true;
    },
    codeClose(value, data, fileParams) {
      if (value && data && data.length > 0) {
        this.fileParams = fileParams;
        this.errorImport.visible = true;
        this.errorImport.data = data;
        this.errorImport.allData = data;
      }
    },
    searchErrorChange(params, done) {
      if (params && params.type) {
        this.errorImport.data = this.errorImport.allData.filter((d) => d.type == params.type);
      } else {
        this.errorImport.data = this.errorImport.allData;
      }
      done();
    },
    searchErrorReset() {
      this.errorImport.data = this.errorImport.allData;
    },
    handleErrorTrue(row, index) {
      this.$set(this.errorImport.data[index], 'dealFlag', true);
      this.$set(this.errorImport.data[index], 'hide', true);
    },
    handleErrorFalse(row, index) {
      this.$set(this.errorImport.data[index], 'dealFlag', false);
      this.$set(this.errorImport.data[index], 'hide', true);
    },
    errorReloadImport() {
      let req = JSON.stringify(this.errorImport.data);
      let fileParams = this.fileParams;
      fileParams.set('req', new Blob([req], { type: 'application/json' }));
      request({
        url: `${this.importConfig.importUrl}?isCovered=false`,
        method: 'post',
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        data: fileParams
      })
        .then((res) => {
          this.$message.success(res.data.msg);
          this.errorImport.visible = false;
        })
        .catch((err) => {})
        .finally(() => {});
    },
    undoScheduleDel(row, index) {
      this.undoSchedule.plan.data.splice(index, 1);
    },
    handleUndoSubmit(form, done) {
      let ids = this.selectionList.map((list) => list.id);
      revokePlan({
        workOrderIdSet: ids,
        reason: form.reason
      }).then((res) => {
        this.undoSchedule.visible = false;
        this.$message.success('撤销成功');
        this.onLoad(this.page);
      });
      done();
    },
    handleUndoReset() {
      this.undoSchedule.visible = false;
    },
    handleView(row) {
      this.planDetailVisible = true;
      this.$nextTick(() => {
        this.$refs.planDetail && this.$refs.planDetail.setWorkOrderInfo(row);
      }, 500);
    },
    searchReset() {
      this.query = {};
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      if (params.planTime) {
        params.planTimeStart = params.planTime[0];
        params.planTimeEnd = params.planTime[1];
        delete params.planTime;
      }
      if (params.type) {
        params.workOrderTypeStr = params.type.join(',');
        delete params.type;
      }
      if (params.status) {
        params.workOrderStatus = params.status.join(',');
        delete params.status;
      }
      if (params.woProcessStatus) {
        params.woProcessStatusStr = params.woProcessStatus.join(',');
        delete params.woProcessStatus;
      }
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud && this.$refs.crud.toggleSelection();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    // 重新加载公用表格弹窗组件
    newKey() {
      this.timer = new Date().getTime();
    }
  }
};
</script>

<style lang="scss" scoped>
::v-deep .dispatchDialog {
  .el-dialog__body {
    padding: 0px 20px 5px;
  }
  .avue-crud__menu {
    min-height: auto;
    margin-bottom: 15px;
  }
  .el-table__fixed-header-wrapper {
    .el-icon-plus {
      cursor: pointer;
      font-weight: bold;
      color: rgb(102, 177, 255);
    }
  }
  .el-table .cell {
    padding-left: 2px;
    padding-right: 2px;
    .el-input-number {
      width: 100%;
    }
  }
  .el-table__body td {
    padding: 0;
  }
  .dispatch-title {
    display: flex;
    align-items: center;
    margin: 15px 0;
    &-dot {
      background-color: rgb(102, 177, 255);
      width: 10px;
      height: 20px;
      margin-right: 8px;
    }
    &-text {
      font-weight: bold;
      font-size: 16px;
    }
  }
  .dispatch-menu {
    display: flex;
    align-items: center;
    justify-content: space-between;
    .leftWorkSection {
      display: flex;
      align-items: center;
      span {
        display: inline-block;
        height: 14px;
        width: 14px;
        margin: 0 3px;
        &.finished {
          background-color: #95f204;
          &:before {
            content: '\2713';
            display: inline-block;
            width: 14px;
            height: 14px;
            color: #fff;
            font-size: 12px;
            vertical-align: super;
          }
        }
        &.finishing {
          background-color: #03a7f0;
        }
        &.notFinish {
          background-color: #ccc;
        }
      }
    }
    .rightInfo {
      display: flex;
      align-items: center;
      .legendList {
        display: flex;
        margin-right: 10px;
        .legendItem {
          display: flex;
          align-items: center;
          margin-right: 3px;
          span {
            display: inline-block;
            height: 14px;
            width: 14px;
            margin-right: 3px;
            &.finished {
              background-color: #95f204;
              &:before {
                content: '\2713';
                display: inline-block;
                width: 14px;
                height: 14px;
                color: #fff;
                font-size: 12px;
                vertical-align: super;
              }
            }
            &.finishing {
              background-color: #03a7f0;
            }
            &.notFinish {
              background-color: #ccc;
            }
          }
        }
      }
      .dateDisplay {
        display: flex;
        align-items: center;
      }
    }
  }
  .workInfoForm {
    .avue-form__group {
      .el-form-item {
        margin-bottom: 5px;
      }
      .avue-form__menu {
        display: none;
      }
    }
  }
  .gannt-menu {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
    .lineResource {
      display: flex;
      .el-form-item {
        margin-bottom: 0;
        display: flex;
        align-items: center;
        .line-cascader {
          .el-cascader__tags {
            flex-wrap: nowrap;
            align-items: center;
            .el-tag:nth-child(1) {
              max-width: 80%;
            }
          }
          .el-cascader__search-input {
            display: none;
          }
        }
      }
    }
    &-button-group {
      display: flex;
      align-items: center;
      .legendList {
        display: flex;
        .legendItem {
          margin-right: 5px;
          display: flex;
          align-items: center;
          span {
            display: inline-block;
            height: 14px;
            width: 14px;
            margin-right: 3px;
            &.finished {
              background-color: #03a7f0;
            }
            &.finishing {
              background-color: #95f204;
            }
            &.notFinish {
              background-color: red;
            }
          }
        }
      }
      .sign {
        margin-left: 10px;
      }
    }
  }
  #gannt-container {
    width: 100%;
    height: 450px;
    .left-container {
      overflow: hidden;
      position: relative;
      height: 100%;
    }
  }
  .el-dialog__footer {
    padding: 10px 20px 10px;
  }
}
::v-deep .undoDialog {
  .avue-crud__menu,
  .avue-form__menu {
    display: none;
  }
  .dispatch-title {
    display: flex;
    align-items: center;
    margin: 20px 0;
    &-dot {
      background-color: rgb(102, 177, 255);
      width: 10px;
      height: 20px;
      margin-right: 8px;
    }
    &-text {
      font-weight: bold;
      font-size: 16px;
    }
  }
}
::v-deep .importErrorDialog {
  .avue-crud__menu {
    display: none;
  }
}
</style>
